/*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    DHTML Calendar
    
    Author  : Darren Neimke
    Source  : http://www.showusyourcode.com/
    Email   : showusyourcode@hotmail.com
    Date    : 29-Aug-2003
    
    Version 4
		
    Kudos to Lea Smart [ http://totallysmartit.com/ ] for helping me to 
    architect this calendar, particularly the issues surrounding NS 6
    integration and general software design.  Without his gentle nudge 
    this product would be far inferior to how it is now.
	
    Changes made by Caitlin Fegan
    to standardise the HTML output and make it lighter and nicer :)
    July 2003

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

// -------------------------------------------
//        Helper classes etc.
// -------------------------------------------


// Visibility enum
var Visibility = new Array()
    Visibility.On = true ;
    Visibility.Off = false ;
            
// Browser class
function Browser()
{
  if ( parseInt( navigator.appVersion.charAt(0) ) >= 4 )
    // Browser check.
    {
      this.isDOM = document.getElementById ? true : false ;
      this.isNav6 = (navigator.appName == "Netscape") ? true : false ;
      this.isNav4 = (navigator.appName == "Netscape" && !(this.isDOM)) ? true : false ;
      this.isIE4 = (navigator.appName.indexOf("Microsoft") != -1) ? true : false ;
    }
}
var browser = new Browser();

        
// -------------------------------------------
//        Global variables, functions etc.
// -------------------------------------------
        
    
// The following variables are global, 
// don't edit them
    
// reference to instance
var gCalendar ;
    
// constructor
    
function gfnCalInitialize()
{
    new suycCalendar(new Date()) ;
}

// Instantiate the calendar
window.onload = function()
{
    gfnCalInitialize() ;
}

    
if(browser.isDOM)
{
 
    document.writeln('<DIV Id="calContainer"></DIV>') ;
}
    
    
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    
                      
function suycCalendar()
{
    gCalendar = this ;
    this.days = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') ;
    this.months = new Array('January','February','March','April','May','June','July','August','September','October','November','December') ;
    this.monthDays = new Array(31,28,31,30,31,30,31,31,30,31,30,31) ;
      
    // Populate the current Day|Month|Year properties
    var objDate = new Date() ;
    this.currentDay = objDate.getDate() ;
    this.currentMonth = objDate.getMonth() ; 
    var curYear = objDate.getYear() ; 
    this.currentYear = (curYear < 1000) ? curYear + 1900 : curYear ;
      
    this.year = this.currentYear ;
    this.month = this.currentMonth ;
      
    this.isVisible = false ;
      
    // Pre-build the top shell
    this.calTopOuter = '<form name="frmCalendar">';
      
    // Pre-build the selector bar
    this.calSelectorBarTop = '<table width="100%" border="0"  cellspacing="0" cellpadding="0" ><tr align="center" class="button"><td><input type="button" name="previousMonth" value="<" onClick="gCalendar.MonthClick(-1) ;">'
        + '&nbsp;<select name="calSelMonth" onChange="gCalendar.MonthOnChange();">' ;
      
    this.calSelectorBarBottom = '&nbsp;<input type="button"   name="nextMonth" value=">" onClick="gCalendar.MonthClick(1) ;"></td></tr></table>';  
      
    // Pre-build the day names bar 
    this.calDayNameBar = '' ;
    for (var i=0; i < this.days.length; i++)
        {
        this.calDayNameBar += '<div class="d" >' + this.days[i].substr(0,2) + '</div>' ; 
        }
    this.calDayNameBar += '' ;
                        
                  
                // Pre-build the bottom shell
                this.calBottomOuter =  '<a href="javascript: void(0) ;" onClick="gCalendar.MoveToCurrent() ;" class="calFooter">Show Today</a>'
                    +'</form>' ;
                  
                  
                  
                // Create the canvass that we will be displaying the calendar on
                this.initCanvass() ;
}


/*********************************************
  Public methods
**********************************************/

    
/*
  Show is called when a user requests a calendar.  The show method
  is passed 4 arguments; the event, the formname, the fieldname
  and and optional dir value of 'right' or left'.  The default for the
  fourth argument is 'right'
*/	
suycCalendar.prototype.Show = function(event, formname, fieldname, dir)
{
    if(this.isVisible == true)
    {
        this.setVisibility(Visibility.Off) ;	 
        return ;
    }
      
    this.setVisibility(Visibility.Off) ;
      
    if(browser.isNav6)
    {
        if (dir == 'left')
        {
            this.x = event.pageX - 183 ;
        }
        else
        {
            this.x = event.pageX + 10 ;
        }
        this.y = event.pageY - 5 ;    
    }
    else if (browser.isNav4)
    {
        if (dir == 'left')
        {
            this.x = event.x - 162 ;
        }
        else
        {
            this.x = event.x + 10 ;
        }
        this.y = event.y - 5 ;    
    }
    else
    {
        var event = window.event ;
        //Set the x pos of the calendar object
        if (dir == 'left')
        {
	        this.x = event.clientX - 180 ;
        }
        else
        {
	        this.x = event.clientX + 22 ;
        }
        //Set the y pos of the calendar object
        this.y = event.clientY - 10 ;
    } 
    this.target = document.forms[formname].elements[fieldname] ;
    this.positionCanvass() ;
    this.setVisibility(Visibility.On) ;
    this.writeString(this.buildString()) ;
 
}

    
/*
  Invoked by the user explicitly closing the calendar
*/
suycCalendar.prototype.Hide = function()
{
    this.x = 0 ;
    this.y = 0 ;
    this.setVisibility(Visibility.Off) ;
}


/*
  Invoked by the user explicitly clicking a
  day on the calendar face
*/
suycCalendar.prototype.DayClick = function(day)
{
    this.target.value = this.formatDate(day) ;
    this.setVisibility(Visibility.Off) ;
}


/*
  Invoked by the user explicitly toggling the
  Month by -1 or +1
*/
suycCalendar.prototype.MonthClick = function(n)
{
    if((this.month + n) < 0)
    {
        this.month = 11 ;
        -- this.year ;
    }
    else if((this.month + n) >= 12) 
    { 
        this.month = 0 ; 
        ++ this.year ; 
    }
    else
    {
        this.month = this.month + n ;
    }
      
    this.writeString(this.buildString()) ;
}


/*
  Invoked by the user explicitly changing the
  text in the year selector
*/
suycCalendar.prototype.YearOnBlur = function()
{
    var tmp = browser.isNav6?this.canvass.ownerDocument.forms[0].calTxtYear:this.canvass.document.forms[0].calTxtYear;
    // TO DO: validate tmp.value
    if ('undefined' != typeof(tmp.value))
    {
    this.year = tmp.value ;
    this.writeString(this.buildString()) ;
    }
    
}


/*
  Invoked by the user explicitly changing the
  month dd selector
*/
suycCalendar.prototype.MonthOnChange = function()
{
    this.month = browser.isNav6?this.canvass.ownerDocument.forms[0].calSelMonth.selectedIndex:this.canvass.document.forms[0].calSelMonth.selectedIndex;
    this.writeString(this.buildString());
}



// Moves the Calendar to the current Month/Year
suycCalendar.prototype.MoveToCurrent = function()
{
    this.year = this.currentYear ;
    this.month = this.currentMonth ;
    this.writeString(this.buildString()) ;
}



    
/*  **********************************************
    Private methods
    **********************************************/
    
    
// Set up the canvass
// Called on initialization of the Class to create the acutal DIV|LAYER Object
suycCalendar.prototype.initCanvass = function()
{
    if (browser.isNav4) 
    { 
        this.canvass = new Layer(200) ;
    }
    else if (browser.isIE4 || browser.isDOM)
    {
        this.canvass = browser.isDOM ? document.getElementById('calContainer') : document.all.calContainer ;
    }
    this.setVisibility(Visibility.Off) ;
}




// overrideable - optional to pass in a Visibility enum
// signatureA =  setVisibility()      // defaults to opposite of current values
// signatureB =  setVisibility(Visibility.[On|Off])
suycCalendar.prototype.setVisibility = function()
{
    if(browser.isNav4)
    {
        if (this.setVisibility.arguments.length == 0)
        {
            this.canvass.visibility = this.isVisible ? 'show' : 'hide' ;
            this.isVisible = !(this.isVisible)
        }
        else
        {
            this.canvass.visibility = this.setVisibility.arguments[0] ? 'show' : 'hide' ;
            this.isVisible = this.setVisibility.arguments[0] ;
        }
    }
    else if (browser.isIE4 || browser.isDOM)
    {
        if (this.setVisibility.arguments.length == 0)
        {
            this.canvass.style.visibility = this.isVisible ? 'visible' : 'hidden' ;
            this.isVisible = !(this.isVisible)
        }
        else
        {
            this.canvass.style.visibility = this.setVisibility.arguments[0] ? 'visible' : 'hidden' ;
            this.isVisible = this.setVisibility.arguments[0] ;
        }
    }      
}   // setVisibility

    
    
// apply Positioning
suycCalendar.prototype.positionCanvass = function()
{
    if ( browser.isNav4 ) 
    { 
        this.canvass.left = this.x ;
        this.canvass.top = this.y ;
    }
    else if ( browser.isIE4 || browser.isDOM )
    {
        this.canvass.style.left = this.x ;
        this.canvass.style.top = this.y ;
    }       
}   // positionCanvass



// builds/accumulates the string
suycCalendar.prototype.buildString = function()
{
  
    // Get the first and last Day numbers of the month being fetched
    var objDate = new Date( this.year, this.month, 1 ) ;
    var firstDayOfMonth = objDate.getDay() ;
    var lastDayOfMonth = this.daysInMonth() ;
    objDate = null ;
    var i = 0 ;
    var numCols = 0 ;
    var numRows = 0 ;
    var currentDay = 0 ;
    var endPadding = '&nbsp;&nbsp;' ;
      
      
    // Work out what month last month was
    var pM = 0 ;
    var pY = 0 ;
    if((this.month - 1) < 0)
    {
        pM = 11 ;
        pY = this.year - 1 ;
    }
    else
    { 
        pM = this.month-1 ;
        pY = this.year ;
    }
    var daysInPreviousMonth = this.daysInMonth(pY, pM) ;
    var startOfPreviousMonth = daysInPreviousMonth - (firstDayOfMonth-1)
      
      
      
    // Start building the calendar body
    var tmpString = this.calTopOuter
    + this.calSelectorBarTop ;
      
    for (var i=0; i < this.months.length; i++)
    {
        tmpString += '<option value="' + i + '"' ;
        if (i == this.month) tmpString += ' selected' ;
        tmpString += '>' + this.months[i].substr(0,3) + '</option>' ;
    }
      
    tmpString += '</select>&nbsp;&nbsp;<input type="text" name="button" value="' + this.year + '"size="1" maxlength="4" onBlur="gCalendar.YearOnBlur();">'
    + this.calSelectorBarBottom
    + this.calDayNameBar ;
      
    // Body of calendar goes here
    var itemNum = 0;
    var fisrt = true;
    tmpString += '' ;
    for(i = 0; i < firstDayOfMonth; i++)
    {
		if(i==0){
			tmpString += '<div class="weekend">' + startOfPreviousMonth++ + '</div>' ;
		}else{
        tmpString += '<div class="lm">' + startOfPreviousMonth++ + '</div>' ;}
        numCols++ ;
        itemNum = i;
        fisrt = false;
    }
    if((itemNum==0)&&(fisrt))
    {
		itemNum = -1;
    }
      
    for(i = 1; i <= lastDayOfMonth; i++)
    {
        // Call the method to create the cell contents
        if(((itemNum+i) % 7 != 0)&&((itemNum+i) % 7 != 6))
        {
			tmpString += '<a href="javascript: void(0) ;" onClick="gCalendar.DayClick(' + i + ') ;"';
        }else
        {
			tmpString += '<div class="weekend"><a href="javascript: void(0) ;" onClick="gCalendar.DayClick(' + i + ') ;"';
        }
        if(this.isToday(i,this.month,this.year))
        {
        tmpString += ' id="today">' + i + '</a>' ;
        }
        else
        {
        tmpString += '>' + i + '</a>' ;
        }
        if(((itemNum+i) % 7 == 0)||((itemNum+i) % 7 == 6))
        {
			tmpString += '</div>';
        }      
        
        numCols++ ;
        
        /* Display new row after each 7 day block.  */
        if (numCols % 7 == 0)
        {
        numRows++ ;
        }
    }
    itemNum += lastDayOfMonth;
      
    var counterCols = numCols ;
    var j = 1 ;
    for(i = counterCols; i < 42; i++)
    {
        // Call the method to create the cell contents
        if(((itemNum+j) % 7 != 0)&&((itemNum+j) % 7 != 6))
        {
        tmpString += '<div class="lm">' + j++ + '</div>' ;
        }else
        {
        tmpString += '<div class="weekend">' + j++ + '</div>' ;
        }
        numCols++ ;
        
    }
      
    // End of BODY
      
    tmpString += this.calBottomOuter ;
      
    return tmpString ;          
}   // buildString



// renders string to canvass
suycCalendar.prototype.writeString = function(s)
{
    if(browser.isNav4)
    {
        this.canvass.document.open() ;
        this.canvass.document.writeln(s) ;
        this.canvass.document.close() ;
    }
    else if (browser.isIE4 || browser.isDOM)
    {
        this.canvass.innerHTML = s ;
    }          
}   // writeString


suycCalendar.prototype.formatDate = function(n)
{
    //return '' + n + '-' + this.months[this.month].substr(0,3) + '-' + this.year ; 
    var tmpmonth = this.month + 1;
	if( tmpmonth <10) { tmpmonth = "0"+tmpmonth; }
	var tmpn = n;
	if( tmpn <10 ) { tmpn = "0"+n; }
    //return '' + tmpn + '/' + tmpmonth + '/' + this.year ; 
    return this.year + '-' + tmpmonth + '-' + tmpn;
}



// sets the chosen value in the target element
suycCalendar.prototype.setValue = function()
{
    try
    {
        targetEnabled = this.target.disabled ;
        this.target.disabled = false ;
        this.target.value = this.getFormattedDate() ;
        this.target.disabled = targetEnabled ;
    }
    catch(e)
    {
        var message ;
        message = '-----------------\n'
        + '\t Calendar error! \n\n'
        + 'An error has occurred.\n'
        + 'The chosen value cannot be \n'
        + 'written to the target field.\n'
        + '-----------------' ;
        alert(message) ;
    }
}   // setValue
    
    
    
    // overrideable - optional to pass in yy/dd
    // signatureA =  daysInMonth()      // defaults to this.year, this.month
    // signatureB =  daysInMonth(y,m)
suycCalendar.prototype.daysInMonth = function()
{
    var oride = (this.daysInMonth.arguments.length == 2) ;
      
    var year = oride ? this.daysInMonth.arguments[0] : this.year ;
    var month = oride ? this.daysInMonth.arguments[1] : this.month ;
      
    if(month == 1 && this.isLeapYear(year))
    return (29) ;
    else
    return(this.monthDays[month]) ;
  
}   // daysInMonth


    // used to compare a date to TODAY.  Used to color today.
suycCalendar.prototype.isToday = function(d,m,y)
{
  
    var now = new Date() ;
    var today = new Date(now.getYear(),now.getMonth(),now.getDate()) ;
    var date = new Date(y,m,d) ;
    return (date.toString() == today.toString());
  
}   // isToday



    // helper function
suycCalendar.prototype.isLeapYear = function()
{
    if (this.year % 4 == 0 && (this.year % 100 != 0 || this.year % 400 == 0))
    return(true) ; return(false) ;
}   // isLeapYear


function handleDocumentClick(e)
{
    if (browser.isIE4) e = window.event;
  
    if (browser.isNav6)
    {
        var bTest = (e.pageX > parseInt(gCalendar.canvass.style.left) && e.pageX <  (parseInt(gCalendar.canvass.style.left) + 162) && e.pageY < (parseInt(gCalendar.canvass.style.top)+163) && e.pageY > parseInt(gCalendar.canvass.style.top));
        if ((e.target.name != 'imgCalendar' && e.target.name != 'calSelMonth') && !(bTest))
	    {
	        gCalendar.Hide() ; 
	    }
    }
  
    if (browser.isIE4)
    {
		if(gCalendar != null)
		{
			// extra test to see if user clicked inside the calendar but not on a valid date, we don't want it to disappear in this case
			var bTest = (e.x > parseInt(gCalendar.canvass.style.left) && e.x <  (parseInt(gCalendar.canvass.style.left) + 160) && e.y < (parseInt(gCalendar.canvass.style.top)+141) && e.y > parseInt(gCalendar.canvass.style.top));
			if ((e.srcElement.name != 'imgCalendar' && e.srcElement.name != 'calSelMonth') && !(bTest))
			{
				gCalendar.Hide(); 
			}
	    }
    }
  
    if (browser.isNav4) gCalendar.Hide(); 
}


document.onclick = handleDocumentClick